package org.example.notice.facade;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import org.example.api.notic.response.NoticeResponse;
import org.example.api.notic.service.NoticeFacadeService;
import org.example.base.exception.SystemException;
import org.example.limiter.SlidingWindowRateLimiter;
import org.example.notice.domain.constant.NoticeState;
import org.example.notice.domain.entity.Notice;
import org.example.notice.domain.service.NoticeService;
import org.example.sms.SmsService;
import org.example.sms.response.SmsSendResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import static org.example.api.notic.constant.NoticeConstant.CAPTCHA_KEY_PREFIX;
import static org.example.base.exception.BizErrorCode.SEND_NOTICE_DUPLICATED;

public class NoticeFacadeServiceImpl implements NoticeFacadeService {

    @Autowired
    private SlidingWindowRateLimiter slidingWindowRateLimiter;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private NoticeService noticeService;

    @Autowired
    private SmsService smsService;

    /**
     * 生成短信验证码
     * @param telephone
     * @return
     */
    @Override
    public NoticeResponse generateAndSendSmsCaptcha(String telephone) {
        // 先判断是否可以发送
        Boolean access = slidingWindowRateLimiter.tryAcquire(telephone, 1, 60);
        if(!access){
            // 已经发送过验证码 不允许重复发送
            throw new SystemException(SEND_NOTICE_DUPLICATED);
        }
        // 生成验证码
        String captcha = RandomUtil.randomNumbers(4);
        // 存入到redis中 并设置5分钟过期时间
        redisTemplate.opsForValue().set(CAPTCHA_KEY_PREFIX + telephone,captcha,5, TimeUnit.MINUTES);

        Notice notice = noticeService.saveCaptcha(telephone, captcha);
        Thread.ofVirtual().start(() -> {
            SmsSendResponse result = smsService.sendMsg(notice.getTargetAddress(), notice.getNoticeContent());
            if (result.getSuccess()) {
                notice.setState(NoticeState.SUCCESS);
                notice.setSendSuccessTime(new Date());
                noticeService.updateById(notice);
            } else {
                notice.setState(NoticeState.FAILED);
                notice.addExtendInfo("executeResult", JSON.toJSONString(result));
                noticeService.updateById(notice);
            }
        });
        return new NoticeResponse.Builder().setSuccess(true).build();
    }
}
